/*
	by Ilija
*/


#include "UTModelLoader.h"


bool UTModelLoader::parseFile(const char *filename, GLModel *model)
{
	FileObject f(filename, FO_READ);
	if (!f.isOpened())
		return false;

    if (strcmp(strrchr(filename, '.'), ".obj") == 0)
    {
        parseFile_OBJ(&f, model);
    }
    else if (strcmp(strrchr(filename, '.'), ".dat") == 0)
    {
        matrix4f m;
        int g = model->pushGroup("main");
        parseFile_LDraw(&f, model, g, 1, m);
    }
    else
    {
        printf("Wrong model file type '%s'!\n", filename);
        return false;
    }
    return true;
}

void UTModelLoader::parseFile_OBJ(FileObject* fo, GLModel *model)
{
	String line;
	float x,y,z;
	GLModel::VERTEX VER[3];
	String name;
    int g = -1;
	while (fo->readLine(line))
	{
		if (line.getChar(0) == '#' || line == "")
			continue;

		String cmd = line.getWord(0);
		if (cmd == "v")
		{
			x = line.getWord(1).getFloatValue();
			y = line.getWord(2).getFloatValue();
			z = line.getWord(3).getFloatValue();
			model->pushVertex(vector3f(x, y, z));
		}
		else if (cmd == "vt")
		{
			x = line.getWord(1).getFloatValue();
			y = line.getWord(2).getFloatValue();
			model->pushTexCoord(vector3f(x, y, 0));
		}
		else if (cmd == "vn")
		{
			x = line.getWord(1).getFloatValue();
			y = line.getWord(2).getFloatValue();
			z = line.getWord(3).getFloatValue();
			model->pushNormal(vector3f(x, y, z));
		}
		else if (cmd == "g")
		{
			name = line.getWord(1);
            g = model->pushGroup(name);
		}
		else if (cmd == "f")
		{
		    if (g == -1)
                g = model->pushGroup("main");
			for (int i = 0; i < 3; i++)
			{
				String sv = line.getWord(i + 1);
				VER[i].V = sv.getWord(0, '/').getIntValue() - 1;
				VER[i].T = sv.getWord(1, '/').getIntValue() - 1;
				VER[i].N = sv.getWord(2, '/').getIntValue() - 1;
			}
            model->pushFace(g, GLModel::FACE(VER[0], VER[1], VER[2]));
		}
	}
}

void UTModelLoader::parseFile_LDraw(FileObject* fo, GLModel* model,
                                    int group, int ccw, const matrix4f& mat)
{
    String line;
    int fo_ln = 0;
	char ss[256];
    int x,y,z,a,b,c,d,e,f,g,h,i;
    int color;
    int tmp;
    vector3f v1,v2,v3,v4;
	while (fo->readLine(line))
	{
		String cmd = line.getWord(0);
		char* sline = line.c_str();
		if (cmd == "0")
        {
            String meta = line.getWord(1);
            if (meta == "//")
            {
                //comment
            }
            else if (meta == "PRINT" || meta == "WRITE")
            {
                printf("LDraw: %s\n", sline);
            }
            else if (meta == "FILE")
            {
                group = model->pushGroup(line.getWord(2));
            }
            else if (meta == "NOFILE")
            {
                group = 0;
            }
            else if (meta == "BFC")
            {
                String arg1 = line.getWord(2);
                String arg2 = line.getWord(3);
                if (arg1 == "CW" || arg2 == "CW" || arg1 == "NOCERTIFY")
                    ccw = 0;
                else if (arg1 == "CCW" || arg2 == "CCW")
                    ccw = 1;
                else
                    printf("LDraw: unknown command '%s' at %s:%i\n",
                           meta.c_str(), fo->getFileName().c_str(), fo_ln);
            }
            else
            {
                printf("LDraw: unknown command '%s' at %s:%i\n",
                       meta.c_str(), fo->getFileName().c_str(), fo_ln);
            }
        }
        else if (cmd == "1")
        {
            sscanf(sline, "%i %i %i%i%i %i%i%i%i%i%i%i%i%i %s",
                   &tmp, &color, &x,&y,&z, &a,&b,&c,&d,&e,&f,&g,&h,&i, ss);
            matrix4f mm(a, d, g, 0,
                        b, e, h, 0,
                        c, f, i, 0,
                        x, y, z, 1);
            FileObject ff(ss, FO_READ);
            parseFile_LDraw(&ff, model, group, ccw, mm);
        }
        else if (cmd == "2")
        {
            printf("LDraw: %s\n", sline);
        }
        else if (cmd == "3")
        {
            sscanf(sline, "%i %i %i%i%i %i%i%i %i%i%i",
                   &tmp, &color,
                   &x,&y,&z,
                   &a,&b,&c,
                   &d,&e,&f);
            v1 = vector3f(x, y, z) * mat;
            v2 = vector3f(a, b, c) * mat;
            v3 = vector3f(d, e, f) * mat;
            GLModel::VERTEX A,B,C;
            A.V = model->pushVertex(v1);
            B.V = model->pushVertex(v2);
            C.V = model->pushVertex(v3);
            if (ccw)
            {
                model->pushFace(group, GLModel::FACE(A,B,C));
            }
            else
            {
                model->pushFace(group, GLModel::FACE(C,B,A));
            }
        }
        else if (cmd == "4")
        {
            sscanf(sline, "%i %i %i%i%i %i%i%i %i%i%i %i%i%i",
                   &tmp, &color,
                   &x,&y,&z,
                   &a,&b,&c,
                   &d,&e,&f,
                   &g,&h,&i);
            v1 = vector3f(x, y, z) * mat;
            v2 = vector3f(a, b, c) * mat;
            v3 = vector3f(d, e, f) * mat;
            v4 = vector3f(g, h, i) * mat;
            GLModel::VERTEX A,B,C,D;
            A.V = model->pushVertex(v1);
            B.V = model->pushVertex(v2);
            C.V = model->pushVertex(v3);
            D.V = model->pushVertex(v4);
            if (ccw)
            {
                model->pushFace(group, GLModel::FACE(A,B,C));
                model->pushFace(group, GLModel::FACE(C,D,A));
            }
            else
            {
                model->pushFace(group, GLModel::FACE(C,B,A));
                model->pushFace(group, GLModel::FACE(A,D,C));
            }
        }
        else if (cmd == "5")
        {
            printf("LDraw: %s\n", sline);
        }
        fo_ln++;
	}
}


